//
//  ViewController.m
//  SocketTelnet
//
//  Created by Hur Song on 12. 12. 10..
//  Copyright (c) 2012년 song. All rights reserved.
//
//sudo -s launchctl load -w /System/Library/LaunchDaemons/ftp.plist 

#define		PORT 21
#define		BUFF_SIZE   10240
#define		STRLEN		100
#define		PORTLEN		28

#import "ViewController.h"


@implementation ViewController

	@synthesize ipAddrLabel = _ipAddrLabel;
	@synthesize portLabel = _portLabel;
	@synthesize massageLabel = _massageLabel;
	@synthesize command_socket = _command_socket;
	@synthesize data_client = _data_client;
	@synthesize connectButton = _connectButton;
	@synthesize disconnectButton = _disconnectButton;
	@synthesize listData = _listData;
	@synthesize socketAddr;
	@synthesize dataListTableViewController = _dataListTableViewController;


	struct _dataChannel {
		char	ip[STRLEN];
		char	chaIp[STRLEN];
		unsigned short  port;
		char	chaPort[STRLEN];
		int	c_sock;
	} dataChannel;

	- (void)viewDidLoad
	{
		[super viewDidLoad];
		self.listData = [[NSMutableArray alloc] initWithCapacity:0];
	}

	- (void)didReceiveMemoryWarning
	{
		[super didReceiveMemoryWarning];
	}


	- (IBAction)respondsToConnect:(id)sender
	{
		NSString * connectIPAddr = _ipAddrLabel.text;
		NSUInteger portNum = [_portLabel.text integerValue];
		_command_socket = socket(PF_INET, SOCK_STREAM, 0);

		
		socketAddr.sin_len = sizeof(socketAddr);
		socketAddr.sin_family = AF_INET;
		socketAddr.sin_port = htons(portNum);
		socketAddr.sin_addr.s_addr = inet_addr([connectIPAddr cStringUsingEncoding:NSUTF8StringEncoding]);
		
		if (connect(_command_socket, (struct sockaddr *)&socketAddr, sizeof(socketAddr)) < 0)
		{
			perror("connect error ");
			self.disconnectButton.hidden = YES;
			self.connectButton.hidden = NO;
		}
		else
		{
			self.disconnectButton.hidden = NO;
			self.connectButton.hidden = YES;
			[self recvResponse];
			
			[_ipAddrLabel resignFirstResponder];
			[_portLabel resignFirstResponder];
		}
		
	}

	- (IBAction)respondsToDisconnect:(id)sender
	{
		send(_command_socket, "QUIT\r\n", strlen("QUIT\r\n"),0);

		close(_command_socket);
		self.disconnectButton.hidden = YES;
		self.connectButton.hidden = NO;
		self.massageLabel.text = @"";
	}


	- (IBAction)respondsToLogin:(id)sender
	{
		send(_command_socket, "user anonymous\r\n",strlen("user anonymous\r\n"),0);
		[self recvResponse];
		
		send(_command_socket, "pass \r\n",strlen("pass \r\n"),0);
		[self recvResponse];
	}

	- (IBAction)respondsToGetList:(id)sender
	{
		send(_command_socket, "LIST\r\n", strlen("LIST\r\n"),0);
		[self openDataChannel];
		[self recvResponse];
		[self recvData];
	}

	- (IBAction)respondsToPort:(id)sender
	{
		char	sndBuf[BUFSIZ];
		
		[self make_ip];
		
		sprintf(sndBuf, "PORT %s\r\n", dataChannel.chaPort);
		send(_command_socket, sndBuf, strlen(sndBuf),0);
		
//		sprintf(sndBuf, "PASV\r\n");
//		send(_connect_client, sndBuf, strlen(sndBuf),0);
		
		[self recvResponse];
	}

	- (void)handleChangeDirectory:(NSString*)target
	{
		char	sndBuf[BUFSIZ];
		char	rcvBuf[BUFSIZ];
		NSLog(@"target : %@", target);
		// send CWD
		sprintf(sndBuf, "CWD %s", [target cStringUsingEncoding:NSUTF8StringEncoding]);
		send(_command_socket, sndBuf, strlen(sndBuf),0);
		
		memset(rcvBuf, 0, BUFSIZ);
		[self recvResponse];
		
		[self respondsToGetList:nil];
//		[self handleGetList];
		
		return;
	}

	- (void)handleGetList
	{
		NSUInteger	len;
		struct  sockaddr_in c_addr;
		send(_command_socket, "LIST\r\n", strlen("LIST\r\n"),0);

		if(listen(_data_client, 1) == -1) {
			fprintf(stderr, "listen error\n");
			return;
		}
		
		len = sizeof(c_addr);
		if((dataChannel.c_sock = accept(_data_client, (struct sockaddr *) &c_addr, &len)) == -1) {
			fprintf(stderr, "accept error\n");
			return;
		}
		
		[self recvResponse];
		[self recvData];

	}
	- (int) recvResponse
	{
		int i;
		char   buff[BUFF_SIZE] = {'\0', };

		if (recv(_command_socket, buff, BUFF_SIZE, 0) == -1)
		{
			perror("recv");
			return 0;
		}
		for(i=(strlen(buff) - 1);i>0;i--) {
			if(buff[i]=='.' || buff[i]=='\r') {
				buff[i+1]='\0';
				break;
			}
		}
		NSLog(@"%@",[NSString stringWithCString:(const char*)buff encoding:NSUTF8StringEncoding]);
		return 0;
	}

	- (void)recvData
	{
		int	n = 0;
		char	rcvBuf[BUFSIZ] = {0, };
		char	tempBuf[BUFSIZ] = {0, };
		
		while((n = read(dataChannel.c_sock, rcvBuf, 1)) > 0)
		{
			strcat(tempBuf, rcvBuf);

			if (rcvBuf[0] == '\n')
			{
				[_listData addObject:[NSString stringWithCString:(const char*)tempBuf encoding:NSUTF8StringEncoding]];
				memset(tempBuf, 0, BUFSIZ);
			}
//			printf("%s", tempBuf);
			memset(rcvBuf, 0, BUFSIZ);

		}

		self.dataListTableViewController = [DataListTableView dataListTableViewController:_listData];
		_dataListTableViewController.dataDelegate = self;
		[self.navigationController pushViewController:_dataListTableViewController animated:YES];
		close(dataChannel.c_sock);
	}

	- (void) openDataChannel
	{
		int	option = 8;
		int	optlen;
		struct  sockaddr_in data_addr, c_addr;
		NSUInteger	len;
		
		if((_data_client = socket(PF_INET, SOCK_STREAM, 0)) < 0)
		{
			fprintf(stderr, "data socket open error\n");
			return;
		}
		
		optlen = sizeof(option);
		setsockopt(_data_client, SOL_SOCKET, SO_REUSEADDR, &option, optlen);
		
		memset(&data_addr, 0, sizeof(data_addr));
		data_addr.sin_family = AF_INET;
		data_addr.sin_addr.s_addr = inet_addr(dataChannel.ip);
		data_addr.sin_port = htons(dataChannel.port);
		
		if(bind(_data_client, (struct sockaddr *) &data_addr, sizeof(data_addr)) == -1) {
			fprintf(stderr, "bind error\n");
			return;
		}
		
		if(listen(_data_client, 1) == -1) {
			fprintf(stderr, "listen error\n");
			return;
		}
		
		len = sizeof(c_addr);
		if((dataChannel.c_sock = accept(_data_client, (struct sockaddr *) &c_addr, &len)) == -1) {
			fprintf(stderr, "accept error\n");
			return;
		}
	}



	-(void) make_ip
	{
		unsigned short np1, np2, np3;
		char	chaPort1[PORTLEN], chaPort2[PORTLEN];
		
		const int	 MAX_NIC = 10;
		const char	*localip = "10.23.1.227";
//      const char	*localip = "172.30.1.3"; //집
		struct ifconf ifc;
		struct ifreq ifr[MAX_NIC];
		int	nIF;
		int	s;
		int	cmd = SIOCGIFCONF;
		char	ip[PORTLEN], chaIP[PORTLEN];
		int	i;
		struct in_addr addr;
		
		// make IP
		ifc.ifc_len = sizeof(ifr);
		ifc.ifc_ifcu.ifcu_req = ifr;
		
		if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
			fprintf(stderr, "socket open error");
		}
		
		if(ioctl(s, cmd, &ifc) < 0) {
			fprintf(stderr, "IOCTL error");
		}
		close(s);
		
		nIF = ifc.ifc_len / sizeof(struct ifreq);
		strcpy(ip, localip);
		
		for(i=0; i < nIF; i++) {
			if(ifc.ifc_ifcu.ifcu_req[i].ifr_ifru.ifru_addr.sa_family != AF_INET) {
				continue;
			}
			
			addr = ((struct sockaddr_in *)&ifc.ifc_ifcu.ifcu_req[i].ifr_ifru.ifru_addr)->sin_addr;
			if(addr.s_addr == htonl(0x7f000001)) {
				continue;
			}
			strcpy(ip, inet_ntoa(addr));
		}
		
		strcpy(dataChannel.ip, ip);
		
		i = 0;
		while(*(ip + i) != '\0') {
			if(*(ip + i) == '.')
				chaIP[i] = ',';
			else
				chaIP[i] = *(ip + i);
			i++;
		}
		chaIP[i] = '\0';
		strcpy(ip, chaIP);
		strcpy(dataChannel.chaIp, ip);
		
		// make port
		np1 = np2 = np3 = 0;
		
		srand(rand( ) % (time(NULL)));
		
		np1 = (random( ) % 248) + 7;
		np2 = random( ) % 255;
		np3 = (np1 * 256) + np2;
		
		dataChannel.port = np3;
		sprintf(chaPort1, ",%d", np1);
		sprintf(chaPort2, ",%d", np2);

		strcat(chaPort1, chaPort2);
		strcat(ip, chaPort1);
		strcpy(dataChannel.chaPort, ip);
	}

@end
